package com.sita.cfmoto.ui.fragments;

import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;

import com.alibaba.fastjson.JSONObject;
import com.amap.api.location.CoordinateConverter;
import com.amap.api.location.DPoint;
import com.amap.api.maps.AMap;
import com.amap.api.maps.AMapOptions;
import com.amap.api.maps.CameraUpdate;
import com.amap.api.maps.CameraUpdateFactory;
import com.amap.api.maps.TextureMapView;
import com.amap.api.maps.UiSettings;
import com.amap.api.maps.model.BitmapDescriptor;
import com.amap.api.maps.model.BitmapDescriptorFactory;
import com.amap.api.maps.model.CameraPosition;
import com.amap.api.maps.model.Circle;
import com.amap.api.maps.model.CircleOptions;
import com.amap.api.maps.model.LatLng;
import com.amap.api.maps.model.Marker;
import com.amap.api.maps.model.MarkerOptions;
import com.amap.api.maps.model.MyTrafficStyle;
import com.kymjs.rxvolley.RxVolley;
import com.kymjs.rxvolley.client.HttpCallback;
import com.kymjs.rxvolley.client.HttpParams;
import com.sita.cfmoto.R;
import com.sita.cfmoto.event.FetchVehicleLocEvent;
import com.sita.cfmoto.rest.model.BindedVehicle;
import com.sita.cfmoto.rest.model.request.CfmotorCommonRequest;
import com.sita.cfmoto.support.Constants;
import com.sita.cfmoto.support.GlobalContext;
import com.sita.cfmoto.utils.BitmapUtils;
import com.sita.cfmoto.utils.LogUtils;
import com.sita.cfmoto.utils.VehicleUtils;
import com.sita.cfmoto.utils.L;

import de.greenrobot.event.EventBus;

/**
 * Class BasicMapFragment contains own location marker
 *
 * @author markman on 16/02/15.
 */
public class BasicMapFragment extends Fragment implements AMap.OnMapLoadedListener {

    private static final String TAG = "BasicMapFragment";
    private final int mCircleFilled = Color.argb(0x3f, 0x62, 0x99, 0xf6);
    private final int mCircleEdge = Color.argb(0xff, 0x62, 0x99, 0xf6);
    private final int mEdgeWidth = 3;
    protected AMap aMap;
    protected TextureMapView mapView;
    protected Marker myMarker;
    protected Marker vehicleMarker;
    protected Marker circleCenterMarker;
    protected UiSettings mUiSettings;
    protected boolean mIsStartLocationClient = false;
    protected boolean mIsFollowingMode = false;
    protected boolean mIsShowMyLocation = true;
    protected boolean mIsShowVehicleLocation = true;
    protected RelativeLayout mTitleBarLayout = null;
    private boolean mShowTitleBar = false;
    private int iconSize;
    private boolean mTrackingStarted = false;
    private boolean mDrawCircled = false;
    private Circle mCircle;
    private int mCircleRadius = 0;
    private Handler mHandler = new Handler();
    private Runnable runnable = new Runnable() {
        @Override
        public void run() {
            fetchVehicleGps();
            mHandler.postDelayed(this, 5000);
        }
    };

    public static BasicMapFragment newInstance(boolean showMyLocation, boolean showVehicleLocation) {
        BasicMapFragment f = new BasicMapFragment();
        Bundle args = new Bundle();
        args.putBoolean("showMyLocation", showMyLocation);
        args.putBoolean("showVehicleLocation", showVehicleLocation);
        f.setArguments(args);
        return f;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        Bundle bundle = getArguments();
        if (bundle != null) {
            mIsShowMyLocation = bundle.getBoolean("showMyLocation");
            mIsShowVehicleLocation = bundle.getBoolean("showVehicleLocation");
        }
        View view = hasCreatedView(inflater, container, savedInstanceState);
        if (view == null) {
            view = inflater.inflate(R.layout.fragment_baisc_map, container, false);
            mapView = (TextureMapView) view.findViewById(R.id.basic_map);
            mTitleBarLayout = (RelativeLayout) view.findViewById(R.id.basic_map_toolbar);
        }

        mapView.onCreate(savedInstanceState);// 此方法必须重写
        initMap();

        if (!EventBus.getDefault().isRegistered(this)) {
            EventBus.getDefault().register(this);
        }
        return view;

    }

    protected View hasCreatedView(LayoutInflater inflater, ViewGroup container,
                                  Bundle savedInstanceState) {
        return null;
    }

    @Override
    public void onResume() {
        super.onResume();
        if (mapView != null) {
            mapView.onResume();
            initMap();
        }
        startTimer();
    }

    @Override
    public void onPause() {
        if (mapView != null) {
            mapView.onPause();
        }
        super.onPause();
        stopTimer();
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        if (mapView != null) {
            mapView.onSaveInstanceState(outState);
        }
    }

    @Override
    public void onDestroy() {
        if (mapView != null) {
            mapView.onDestroy();
            aMap = null;
        }
        if (EventBus.getDefault().isRegistered(this)) {
            EventBus.getDefault().unregister(this);
        }
        stopTimer();
        super.onDestroy();
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
    }

    @Override
    public void onHiddenChanged(boolean hidden) {
        if (hidden) {
            stopTimer();
        } else {
            startTimer();
        }
    }

    @Override
    public void onStart() {
        super.onStart();
    }

    @Override
    public void onStop() {
        super.onStop();
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        if (mapView != null) {
            mapView.onDestroy();
            aMap = null;
        }
    }

    private void initMap() {

        if (aMap == null) {
            aMap = mapView.getMap();
            setMapUi();
        }
        setTraffic();

        iconSize = (int) getResources().getDimension(R.dimen.map_location_icon_size);

        if (mIsShowVehicleLocation) {
            drawVehicleMarker();
        }

        aMap.setOnMapLongClickListener(new AMap.OnMapLongClickListener() {
            @Override
            public void onMapLongClick(LatLng latLng) {
                drawCircle(mCircleRadius, latLng.latitude, latLng.longitude);
//                drawCircleCenterMarker(latLng);
//                moveCamera(latLng);

            }
        });
    }

    public void onEventMainThread(FetchVehicleLocEvent event) {
        if (event.getIdentifier() != null && event.getLatLng() != null) {
            LatLng latLng = event.getLatLng();
            drawVehicleMarker(latLng);
        }
    }

    private void moveCamera(LatLng latLng) {
        CameraPosition cameraPosition;
        cameraPosition = new CameraPosition.Builder()
                .target(latLng).zoom(Constants.DEFAULT_ZOOM_LEVEL).bearing(0).tilt(0).build();
        CameraUpdate update = CameraUpdateFactory.newCameraPosition(cameraPosition);
        aMap.moveCamera(update);
    }

    private void moveCamera(LatLng latLng, float zoom) {
        CameraPosition cameraPosition;
        cameraPosition = new CameraPosition.Builder()
                .target(latLng).zoom(zoom).bearing(0).tilt(0).build();
        CameraUpdate update = CameraUpdateFactory.newCameraPosition(cameraPosition);
        aMap.moveCamera(update);
    }

    private void setMapUi() {
        mUiSettings = aMap.getUiSettings();
        mUiSettings.setZoomControlsEnabled(false);
        mUiSettings.setLogoPosition(AMapOptions.LOGO_POSITION_BOTTOM_LEFT);
        mUiSettings.setScrollGesturesEnabled(true);
    }

    private void setTraffic() {
        MyTrafficStyle myTrafficStyle = new MyTrafficStyle();
        myTrafficStyle.setSeriousCongestedColor(0xff92000a);
        myTrafficStyle.setCongestedColor(0xffea0312);
        myTrafficStyle.setSlowColor(0xffff7508);
        myTrafficStyle.setSmoothColor(0xff00a209);
        aMap.setTrafficEnabled(false);
    }

    @Override
    public void onMapLoaded() {
        L.i("onMapLoaded() successfully");

        LatLng latLng = Constants.DEFAULT_MAP_CENTER_LATLNG;
        moveCamera(latLng);
        if (mIsShowVehicleLocation) {
            drawVehicleMarker();
        }
    }

    /**
     * draw Vehicle marker
     */
    public void drawVehicleMarker() {
        if (VehicleUtils.vehicleBean == null) {
            return;
        }
        LatLng latLng = new LatLng(VehicleUtils.vehicleBean.lat, VehicleUtils.vehicleBean.lng);

        if (vehicleMarker != null && !vehicleMarker.isVisible()) {
            vehicleMarker.destroy();
            vehicleMarker = null;
        }

        if (vehicleMarker == null) {
            Bitmap locationMe = BitmapUtils.zoomBitmap(BitmapFactory.decodeResource(GlobalContext.getGlobalContext().getResources(), R.drawable.location_vehicle), iconSize, iconSize);
            BitmapDescriptor icon = BitmapDescriptorFactory.fromBitmap(locationMe);
            vehicleMarker = aMap.addMarker(new MarkerOptions().draggable(false).icon(icon).position(latLng));
        } else {
            vehicleMarker.setPosition(latLng);
        }

        moveCamera(latLng);
    }

    public void drawVehicleMarker(LatLng latLng) {
        if (latLng == null) {
            return;
        }
        if (vehicleMarker != null && !vehicleMarker.isVisible()) {
            vehicleMarker.destroy();
            vehicleMarker = null;
        }

        if (vehicleMarker == null) {
            Bitmap locationMe = BitmapUtils.zoomBitmap(BitmapFactory
                    .decodeResource(GlobalContext.getGlobalContext().getResources(),
                            R.drawable.location_vehicle), iconSize, iconSize);
            BitmapDescriptor icon = BitmapDescriptorFactory.fromBitmap(locationMe);
            vehicleMarker = aMap.addMarker(new MarkerOptions()
                    .draggable(false).icon(icon).position(latLng).setFlat(true));
        } else {
            vehicleMarker.setPosition(latLng);
        }

        if (mDrawCircled)
            return;
        moveCamera(latLng);

    }

    public void drawCircleCenterMarker(LatLng latLng) {
        if (latLng == null) {
            return;
        }
        if (circleCenterMarker != null && !circleCenterMarker.isVisible()) {
            circleCenterMarker.destroy();
            circleCenterMarker = null;
        }

        if (circleCenterMarker == null) {
            Bitmap locationMe = BitmapUtils.zoomBitmap(BitmapFactory
                    .decodeResource(GlobalContext.getGlobalContext().getResources(),
                            R.drawable.location_me), iconSize, iconSize);
            BitmapDescriptor icon = BitmapDescriptorFactory.fromBitmap(locationMe);
            circleCenterMarker = aMap.addMarker(new MarkerOptions()
                    .draggable(false).icon(icon).position(latLng).setFlat(true));
        } else {
            circleCenterMarker.setPosition(latLng);
        }
    }

    public void drawCircle(int radius) {
        // 绘制一个圆形
        if (aMap != null) {
            mCircleRadius = radius;
            if (mCircle != null) {
                mCircle.remove();
            }
            mCircle = aMap.addCircle(new CircleOptions().center(new LatLng(VehicleUtils.vehicleBean.lat, VehicleUtils.vehicleBean.lng))
                    .radius(radius).strokeColor(mCircleEdge)
                    .fillColor(mCircleFilled).strokeWidth(3));

//        LatLngBounds bounds = new LatLngBounds.Builder()
//                .include()
//                .include(AMapUtil.convertToLatLng(mPoint1))
//                .include(AMapUtil.convertToLatLng(mPoint2))
//                .include(AMapUtil.convertToLatLng(mPoint3))
//                .build();
//        aMap.moveCamera(CameraUpdateFactory
//                .newLatLngBounds(bounds, 50));
            moveCamera(new LatLng(VehicleUtils.vehicleBean.lat, VehicleUtils.vehicleBean.lng), zoomLevel(radius));
            mDrawCircled = true;

            drawCircleCenterMarker(new LatLng(VehicleUtils.vehicleBean.lat, VehicleUtils.vehicleBean.lng));
        }
    }

    private float zoomLevel(int distance) {
        float zoom;
        if (distance > 60000) {
            zoom = 8;
        } else if (distance > 20000) {
            zoom = 9;
        } else if (distance > 10000) {
            zoom = 10;
        } else if (distance > 5000) {
            zoom = 11;
        } else if (distance > 3000) {
            zoom = 12;
        } else if (distance > 1000) {
            zoom = 13;
        } else {
            zoom = 14;
        }
        return zoom;
    }

    public void drawCircle(int radius, double lat, double lng) {
        // 绘制一个圆形
        if (aMap != null) {
            mCircleRadius = radius;
            if (mCircle != null) {
                mCircle.remove();
            }
            mCircle = aMap.addCircle(new CircleOptions().center(new LatLng(lat, lng))
                    .radius(radius).strokeColor(mCircleEdge)
                    .fillColor(mCircleFilled).strokeWidth(3));

//        LatLngBounds bounds = new LatLngBounds.Builder()
//                .include()
//                .include(AMapUtil.convertToLatLng(mPoint1))
//                .include(AMapUtil.convertToLatLng(mPoint2))
//                .include(AMapUtil.convertToLatLng(mPoint3))
//                .build();
//        aMap.moveCamera(CameraUpdateFactory
//                .newLatLngBounds(bounds, 50));
            moveCamera(new LatLng(lat, lng), zoomLevel(radius));
            mDrawCircled = true;
            drawCircleCenterMarker(new LatLng(lat, lng));
        }
    }

    public void setMapCenter(double lat, double lng, int distance) {
        drawCircle(distance, lat, lng);
    }

//    public void cancelTask() {
//        mTrackingStarted = false;
//        WakefulIntentService.cancelAlarms(getContext());
//    }
//
//    public void startTask() {
//        // start timer task
//        mTrackingStarted = true;
//        WakefulIntentService.scheduleAlarms(new FetchVehicleGpsListener(), getContext());
//    }

    public void setMapCenter(double lat, double lng) {
        drawCircle(mCircleRadius, lat, lng);
    }

    public LatLng getCircleCenter() {
        if (mCircle != null) {
            return mCircle.getCenter();
        }
        return new LatLng(VehicleUtils.vehicleBean.lat, VehicleUtils.vehicleBean.lng);
    }

    private void startTimer() {
        fetchVehicleGps();
        mHandler.postDelayed(runnable, 5000);
    }

    private void stopTimer() {

        mHandler.removeCallbacks(runnable);

    }

    private void fetchVehicleGps() {
        String url = Constants.BASE_URI + "/yadea/v1/machine/local_impl";
//        Log.i(TAG, "fetchVehicleGps() from " + url);

        BindedVehicle bindedVehicle = VehicleUtils.getCurrentSelectedVehicle();
        if (bindedVehicle == null) {
            return;
        }

        CfmotorCommonRequest request = new CfmotorCommonRequest();
        request.vin = bindedVehicle.vin;
        request.vinCpy = bindedVehicle.vincpy;
        String jsonParam = JSONObject.toJSONString(request);

        HttpParams params = new HttpParams();
        params.putJsonParams(jsonParam);

        //http请求的回调，内置了很多方法，详细请查看源码
        //包括在异步响应的onSuccessInAsync():注不能做UI操作
        //网络请求成功时的回调onSuccess()
        //网络请求失败时的回调onFailure():例如无网络，服务器异常等
        HttpCallback callback = new HttpCallback() {
            @Override
            public void onSuccess(String t) {
                JSONObject rootObj = JSONObject.parseObject(t);
                String errorCode = rootObj.getString("errorCode");
                if ("0".equals(errorCode)) {
                    try {
                        JSONObject dataObj = rootObj.getJSONObject("data");
                        double latitude = dataObj.getDoubleValue("lat");
                        double longitude = dataObj.getDoubleValue("lng");
                        DPoint point = new CoordinateConverter(GlobalContext.getGlobalContext())
                                .from(CoordinateConverter.CoordType.GPS)
                                .coord(new DPoint(latitude, longitude)).convert();
                        LatLng latLng = new LatLng(point.getLatitude(), point.getLongitude());
                        // save the location
                        VehicleUtils.updateLocation(latLng);
                        EventBus.getDefault().post(new FetchVehicleLocEvent()
                                .withIdentifier(bindedVehicle.vin)
                                .withLatLng(latLng));
                    } catch (Exception e) {
                        LogUtils.d("FETCHGPS", "coordinate convert failed");
                    }
                }
            }

            @Override
            public void onFailure(int errorNo, String strMsg) {
                L.e("fetchVehicleGps() --> get error code " + errorNo + ", " + strMsg);
            }
        };

        new RxVolley.Builder()
                .url(url) //接口地址
                //请求类型，如果不加，默认为 GET 可选项：
                //POST/PUT/DELETE/HEAD/OPTIONS/TRACE/PATCH
                .httpMethod(RxVolley.Method.POST)
                //设置缓存时间: 默认是 get 请求 5 分钟, post 请求不缓存
                //.cacheTime(0)
                //内容参数传递形式，如果不加，默认为 FORM 表单提交，可选项 JSON 内容
                .contentType(RxVolley.ContentType.JSON)
                .params(params) //上文创建的HttpParams请求参数集
                //是否缓存，默认是 get 请求 5 缓存分钟, post 请求不缓存
                .shouldCache(false)
                .callback(callback) //响应回调
                .encoding("UTF-8") //编码格式，默认为utf-8
                .doTask();  //执行请求操作
    }

}
